#include <linux/module.h>
#include <linux/kernel.h>

/**
 * @struct gdt_entry
 * @brief 结构体表示一个全局描述符表（GDT）条目
 * 
 * 该结构体包含了GDT条目的基本信息，包括基地址、段界限和属性标志等。
 */
struct gdt_entry {
    __u16 limit0;            ///< 段界限的低16位
    __u16 base0;             ///< 基地址的低16位
    __u16 base1: 8,          ///< 基地址的中间8位
           type: 4,          ///< 段类型
           s: 1,             ///< 描述符类型，0为系统段，1为代码或数据段
           dpl: 2,           ///< 描述符特权级
           p: 1;             ///< 段存在标志
    __u16 limit1: 4,         ///< 段界限的高4位
           avl: 1,           ///< 系统软件可用位
           l: 1,             ///< 64位代码段标志
           d: 1,             ///< 默认操作数大小
           g: 1,             ///< 段界限粒度
           base2: 8;         ///< 基地址的高8位
} __attribute__((packed));

/**
 * @brief 内核模块初始化函数
 * 
 * 模块加载时调用此函数，读取并打印全局描述符表（GDT）的基本地址和每个条目的详细信息。
 * 
 * @return int 成功返回0
 */
static int __init gdt_init(void)
{
    struct desc_ptr gdtr;          ///< GDT寄存器结构
    struct gdt_entry *gdt;         ///< 指向GDT的指针
    unsigned int i;                ///< 循环变量

    // 使用汇编指令加载GDTR寄存器到gdtr变量
    asm volatile("sgdt %0" : "=m" (gdtr));

    printk(KERN_INFO "GDTR base address: %lx, size: %x\n", gdtr.address, gdtr.size);  ///< 打印GDTR的基地址和大小

    gdt = (struct gdt_entry *)gdtr.address;

    for (i = 0; i < gdtr.size / sizeof(struct gdt_entry); i++) {
        unsigned long base = (gdt[i].base0) |
                             (gdt[i].base1 << 16) |
                             (gdt[i].base2 << 24);
        unsigned long limit = gdt[i].limit0 |
                              (gdt[i].limit1 << 16);

        // 打印每个GDT条目的基地址和段界限
        printk(KERN_INFO "GDT Entry %d: Base = %lx, Limit = %lx\n", i, base, limit);
    }
    return 0;  ///< 返回初始化成功
}

/**
 * @brief 内核模块清理函数
 * 
 * 模块卸载时调用此函数，打印退出日志信息。
 */
static void __exit gdt_exit(void)
{
    printk(KERN_INFO "GDT module exited.\n"); ///< 打印模块卸载信息
}

module_init(gdt_init); ///< 指定模块初始化函数
module_exit(gdt_exit); ///< 指定模块退出函数

MODULE_LICENSE("GPL"); ///< 指定模块许可证为GPL
MODULE_DESCRIPTION("GDT Printer Module"); ///< 模块描述
MODULE_AUTHOR("Zhenxiong Chen"); ///< 模块作者
